source: psi/trunk/src/tools/dirwatch/dirwatch.cpp

Last change on this file was 2, checked in by dmik, 19 years ago

Imported original Psi 0.10 sources from Affinix

File size: 5.3 KB
Line 
1/*
2 * dirwatch.cpp - detect changes of directory content
3 * Copyright (C) 2003 Justin Karneges
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 *
19 */
20
21#include"dirwatch.h"
22
23#include<qdir.h>
24#include<qfileinfo.h>
25#include<qvaluelist.h>
26#include<qstringlist.h>
27#include<qtimer.h>
28
29static DirWatchPlatform *platform = 0;
30static int platform_ref = 0;
31
32struct file_info
33{
34 QString name;
35 uint size;
36 QDateTime lastModified;
37};
38
39typedef QValueList<file_info> DirInfo;
40
41static DirInfo getDirInfo(const QString &dir)
42{
43 DirInfo info;
44 QDir d(dir);
45 if(!d.exists())
46 return info;
47 QStringList el = d.entryList();
48 for(QStringList::ConstIterator it = el.begin(); it != el.end(); ++it) {
49 if(*it == "." || *it == "..")
50 continue;
51 QFileInfo fi(d.filePath(*it));
52 file_info i;
53 i.name = fi.fileName();
54 i.size = fi.size();
55 i.lastModified = fi.lastModified();
56 info += i;
57 }
58 return info;
59}
60
61class DirWatch::Private
62{
63public:
64 Private() {}
65
66 QString dir;
67
68 // for non-platform watching
69 DirInfo info;
70 QTimer checkTimer;
71 int freq;
72 int id;
73};
74
75DirWatch::DirWatch(const QString &dir, QObject *parent)
76:QObject(parent)
77{
78 d = new Private;
79 d->freq = 5000;
80 d->id = -1;
81
82 // try to use platform
83 if(!platform) {
84 DirWatchPlatform *p = new DirWatchPlatform;
85 if(p->init())
86 platform = p;
87 else
88 delete p;
89 }
90 if(platform) {
91 ++platform_ref;
92 connect(platform, SIGNAL(dirChanged(int)), SLOT(pf_dirChanged(int)));
93 }
94 else {
95 connect(&d->checkTimer, SIGNAL(timeout()), SLOT(doCheck()));
96 }
97
98 if(!dir.isEmpty())
99 setDir(dir);
100}
101
102DirWatch::~DirWatch()
103{
104 setDir("");
105
106 if(platform) {
107 --platform_ref;
108 if(platform_ref == 0) {
109 delete platform;
110 platform = 0;
111 }
112 }
113 delete d;
114}
115
116bool DirWatch::usingPlatform() const
117{
118 return (platform ? true: false);
119}
120
121QString DirWatch::dir() const
122{
123 return d->dir;
124}
125
126void DirWatch::setDir(const QString &s)
127{
128 if(d->dir == s)
129 return;
130
131 if(!d->dir.isEmpty()) {
132 if(platform) {
133 if(d->id != -1)
134 platform->removeDir(d->id);
135 }
136 else
137 d->checkTimer.stop();
138
139 d->dir = "";
140 }
141
142 if(s.isEmpty())
143 return;
144
145 d->dir = s;
146
147 if(platform) {
148 d->id = platform->addDir(d->dir);
149 }
150 else {
151 d->info = getDirInfo(d->dir);
152 d->checkTimer.start(d->freq);
153 }
154}
155
156void DirWatch::doCheck()
157{
158 DirInfo newInfo = getDirInfo(d->dir);
159
160 bool info_changed = false;
161 QDir dir(d->dir);
162 file_info ni;
163
164 // look for files that are missing or modified
165 for(DirInfo::ConstIterator it = d->info.begin(); it != d->info.end(); ++it) {
166 const file_info &i = *it;
167
168 bool found = false;
169 for(DirInfo::ConstIterator nit = newInfo.begin(); nit != newInfo.end(); ++nit) {
170 const file_info &tmp = *nit;
171 if(i.name == tmp.name) {
172 found = true;
173 ni = tmp;
174 break;
175 }
176 }
177 if(!found) {
178 //printf("%s: not found\n", i.name.latin1());
179 info_changed = true;
180 break;
181 }
182
183 if(i.lastModified != ni.lastModified || i.size != ni.size) {
184 //printf("%s: modified (is: %s, was: %s)\n", i.name.latin1(), ni.lastModified.toString().latin1(), i.lastModified.toString().latin1());
185 info_changed = true;
186 break;
187 }
188 //printf("%s: no change\n", i.name.latin1());
189 }
190
191 // look for files that have been added
192 for(DirInfo::ConstIterator nit = newInfo.begin(); nit != newInfo.end(); ++nit) {
193 const file_info &i = *nit;
194 bool found = false;
195 for(DirInfo::ConstIterator it = d->info.begin(); it != d->info.end(); ++it) {
196 const file_info &tmp = *it;
197 if(i.name == tmp.name) {
198 found = true;
199 break;
200 }
201 }
202 if(!found) {
203 info_changed = true;
204 break;
205 }
206 }
207
208 d->info = newInfo;
209
210 if(info_changed)
211 changed();
212}
213
214void DirWatch::pf_dirChanged(int id)
215{
216 if(d->id != id)
217 return;
218
219 changed();
220}
221
222
223class FileWatch::Private
224{
225public:
226 Private() {}
227
228 QString fname;
229 DirWatch *dw;
230
231 uint lastSize;
232 QDateTime lastModified;
233};
234
235FileWatch::FileWatch(const QString &fname, QObject *parent)
236:QObject(parent)
237{
238 d = new Private;
239 d->dw = 0;
240 if(!fname.isEmpty())
241 setFileName(fname);
242}
243
244FileWatch::~FileWatch()
245{
246 delete d;
247}
248
249QString FileWatch::fileName() const
250{
251 return d->fname;
252}
253
254void FileWatch::setFileName(const QString &s)
255{
256 if(d->fname == s)
257 return;
258
259 // remove old watch if necessary
260 if(d->dw) {
261 delete d->dw;
262 d->dw = 0;
263 }
264 d->fname = s;
265
266 if(d->fname.isEmpty())
267 return;
268
269 // setup the watch
270 d->dw = new DirWatch("", this);
271 connect(d->dw, SIGNAL(changed()), SLOT(dirChanged()));
272 QFileInfo fi(d->fname);
273 d->lastSize = fi.size();
274 d->lastModified = fi.lastModified();
275 d->dw->setDir(fi.dirPath());
276}
277
278void FileWatch::dirChanged()
279{
280 bool doChange = false;
281 QFileInfo fi(d->fname);
282 if(fi.size() != d->lastSize || fi.lastModified() != d->lastModified)
283 doChange = true;
284 d->lastSize = fi.size();
285 d->lastModified = fi.lastModified();
286
287 if(doChange)
288 changed();
289}
Note: See TracBrowser for help on using the repository browser.