Chris@538
|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
Chris@538
|
2
|
Chris@538
|
3 /*
|
Chris@538
|
4 EasyMercurial
|
Chris@538
|
5
|
Chris@538
|
6 Based on hgExplorer by Jari Korhonen
|
Chris@538
|
7 Copyright (c) 2010 Jari Korhonen
|
Chris@538
|
8 Copyright (c) 2011 Chris Cannam
|
Chris@538
|
9 Copyright (c) 2011 Queen Mary, University of London
|
Chris@538
|
10
|
Chris@538
|
11 This program is free software; you can redistribute it and/or
|
Chris@538
|
12 modify it under the terms of the GNU General Public License as
|
Chris@538
|
13 published by the Free Software Foundation; either version 2 of the
|
Chris@538
|
14 License, or (at your option) any later version. See the file
|
Chris@538
|
15 COPYING included with this distribution for more information.
|
Chris@538
|
16 */
|
Chris@538
|
17
|
Chris@538
|
18 #include "fswatcher.h"
|
Chris@538
|
19
|
Chris@538
|
20 #include <QMutexLocker>
|
Chris@538
|
21 #include <QDir>
|
Chris@538
|
22
|
Chris@538
|
23 #include <deque>
|
Chris@538
|
24
|
Chris@538
|
25 FsWatcher::FsWatcher() :
|
Chris@538
|
26 m_lastToken(0),
|
Chris@538
|
27 m_lastCounter(0)
|
Chris@538
|
28 {
|
Chris@538
|
29 connect(&m_watcher, SIGNAL(directoryChanged(QString)),
|
Chris@538
|
30 this, SLOT(fsDirectoryChanged(QString)));
|
Chris@538
|
31 connect(&m_watcher, SIGNAL(fileChanged(QString)),
|
Chris@538
|
32 this, SLOT(fsFileChanged(QString)));
|
Chris@538
|
33 }
|
Chris@538
|
34
|
Chris@538
|
35 FsWatcher::~FsWatcher()
|
Chris@538
|
36 {
|
Chris@538
|
37 }
|
Chris@538
|
38
|
Chris@538
|
39 void
|
Chris@538
|
40 FsWatcher::setWorkDirPath(QString path)
|
Chris@538
|
41 {
|
Chris@538
|
42 QMutexLocker locker(&m_mutex);
|
Chris@538
|
43 m_watcher.removePaths(m_watcher.directories());
|
Chris@538
|
44 m_watcher.removePaths(m_watcher.files());
|
Chris@538
|
45 m_workDirPath = path;
|
Chris@538
|
46 addWorkDirectory(path);
|
Chris@538
|
47 }
|
Chris@538
|
48
|
Chris@538
|
49 void
|
Chris@538
|
50 FsWatcher::addWorkDirectory(QString path)
|
Chris@538
|
51 {
|
Chris@538
|
52 // QFileSystemWatcher will refuse to add a file or directory to
|
Chris@538
|
53 // its watch list that it is already watching -- fine -- but it
|
Chris@538
|
54 // prints a warning when this happens, which we wouldn't want. So
|
Chris@538
|
55 // we'll check for duplicates ourselves.
|
Chris@538
|
56 QSet<QString> alreadyWatched =
|
Chris@538
|
57 QSet<QString>::fromList(m_watcher.directories());
|
Chris@538
|
58
|
Chris@538
|
59 std::deque<QString> pending;
|
Chris@538
|
60 pending.push_back(path);
|
Chris@538
|
61
|
Chris@538
|
62 while (!pending.empty()) {
|
Chris@538
|
63
|
Chris@538
|
64 QString path = pending.front();
|
Chris@538
|
65 pending.pop_front();
|
Chris@538
|
66 if (!alreadyWatched.contains(path)) {
|
Chris@538
|
67 m_watcher.addPath(path);
|
Chris@538
|
68 }
|
Chris@538
|
69
|
Chris@538
|
70 QDir d(path);
|
Chris@538
|
71 if (d.exists()) {
|
Chris@538
|
72 d.setFilter(QDir::Dirs | QDir::NoDotAndDotDot |
|
Chris@538
|
73 QDir::Readable | QDir::NoSymLinks);
|
Chris@538
|
74 foreach (QString entry, d.entryList()) {
|
Chris@538
|
75 if (entry.startsWith('.')) continue;
|
Chris@538
|
76 QString entryPath = d.absoluteFilePath(entry);
|
Chris@538
|
77 pending.push_back(entryPath);
|
Chris@538
|
78 }
|
Chris@538
|
79 }
|
Chris@538
|
80 }
|
Chris@538
|
81 }
|
Chris@538
|
82
|
Chris@538
|
83 void
|
Chris@538
|
84 FsWatcher::setIgnoredFilePrefixes(QStringList prefixes)
|
Chris@538
|
85 {
|
Chris@538
|
86 QMutexLocker locker(&m_mutex);
|
Chris@538
|
87 m_ignoredPrefixes = prefixes;
|
Chris@538
|
88 }
|
Chris@538
|
89
|
Chris@538
|
90 void
|
Chris@538
|
91 FsWatcher::setIgnoredFileSuffixes(QStringList suffixes)
|
Chris@538
|
92 {
|
Chris@538
|
93 QMutexLocker locker(&m_mutex);
|
Chris@538
|
94 m_ignoredSuffixes = suffixes;
|
Chris@538
|
95 }
|
Chris@538
|
96
|
Chris@538
|
97 int
|
Chris@538
|
98 FsWatcher::getNewToken()
|
Chris@538
|
99 {
|
Chris@538
|
100 QMutexLocker locker(&m_mutex);
|
Chris@538
|
101 int token = ++m_lastToken;
|
Chris@538
|
102 m_tokenMap[token] = m_lastCounter;
|
Chris@538
|
103 return token;
|
Chris@538
|
104 }
|
Chris@538
|
105
|
Chris@538
|
106 QSet<QString>
|
Chris@538
|
107 FsWatcher::getChangedPaths(int token)
|
Chris@538
|
108 {
|
Chris@538
|
109 QMutexLocker locker(&m_mutex);
|
Chris@538
|
110 size_t lastUpdatedAt = m_tokenMap[token];
|
Chris@538
|
111 QSet<QString> changed;
|
Chris@538
|
112 for (QHash<QString, size_t>::const_iterator i = m_changes.begin();
|
Chris@538
|
113 i != m_changes.end(); ++i) {
|
Chris@538
|
114 if (i.value() > lastUpdatedAt) {
|
Chris@538
|
115 changed.insert(i.key());
|
Chris@538
|
116 }
|
Chris@538
|
117 }
|
Chris@538
|
118 m_tokenMap[token] = m_lastCounter;
|
Chris@538
|
119 return changed;
|
Chris@538
|
120 }
|
Chris@538
|
121
|
Chris@538
|
122 void
|
Chris@538
|
123 FsWatcher::fsDirectoryChanged(QString path)
|
Chris@538
|
124 {
|
Chris@538
|
125 {
|
Chris@538
|
126 QMutexLocker locker(&m_mutex);
|
Chris@538
|
127 if (shouldIgnore(path)) return;
|
Chris@538
|
128 size_t counter = ++m_lastCounter;
|
Chris@538
|
129 m_changes[path] = counter;
|
Chris@538
|
130 }
|
Chris@538
|
131 emit changed();
|
Chris@538
|
132 }
|
Chris@538
|
133
|
Chris@538
|
134 void
|
Chris@538
|
135 FsWatcher::fsFileChanged(QString path)
|
Chris@538
|
136 {
|
Chris@538
|
137 QMutexLocker locker(&m_mutex);
|
Chris@538
|
138 }
|
Chris@538
|
139
|
Chris@538
|
140 bool
|
Chris@538
|
141 FsWatcher::shouldIgnore(QString path)
|
Chris@538
|
142 {
|
Chris@538
|
143
|
Chris@538
|
144 }
|
Chris@538
|
145
|