~ubuntu-branches/ubuntu/oneiric/psi/oneiric

« back to all changes in this revision

Viewing changes to cutestuff/dirwatch/dirwatch_win.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jan Niehusmann
  • Date: 2006-01-20 00:20:36 UTC
  • mfrom: (1.2.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20060120002036-7nw6yo6totip0ee5
Tags: 0.10-2
* Added upstream changelog (Closes: Bug#327748)
* Mention --no-gpg and --no-gpg-agent in manpage (Closes: Bug#204416)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * dirwatch_unix.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<qthread.h>
24
 
#include<qptrlist.h>
25
 
#include<qfile.h>
26
 
#include<qdir.h>
27
 
#include<qtimer.h>
28
 
#include<windows.h>
29
 
 
30
 
class DWEvent : public QEvent
31
 
{
32
 
public:
33
 
        DWEvent(int _state)
34
 
        :QEvent(QEvent::User)
35
 
        {
36
 
                state = _state;
37
 
        }
38
 
 
39
 
        int state;
40
 
};
41
 
 
42
 
class DWThread : public QThread
43
 
{
44
 
public:
45
 
        DWThread(QObject *_par, HANDLE _h) : QThread()
46
 
        {
47
 
                par = _par;
48
 
                h = _h;
49
 
        }
50
 
 
51
 
        void run()
52
 
        {
53
 
                while(WaitForSingleObject(h, INFINITE) == WAIT_OBJECT_0) {
54
 
                        // send a changed event
55
 
                        QThread::postEvent(par, new DWEvent(1));
56
 
                        if(!FindNextChangeNotification(h)) {
57
 
                                // send an error event
58
 
                                QThread::postEvent(par, new DWEvent(0));
59
 
                                return;
60
 
                        }
61
 
                }
62
 
        }
63
 
 
64
 
        QObject *par;
65
 
        HANDLE h;
66
 
};
67
 
 
68
 
class DWEntry : public QObject
69
 
{
70
 
        Q_OBJECT
71
 
public:
72
 
        static DWEntry * create(const QString &s)
73
 
        {
74
 
                HANDLE h = FindFirstChangeNotificationA(QFile::encodeName(QDir::convertSeparators(s)), TRUE,
75
 
                        FILE_NOTIFY_CHANGE_FILE_NAME |
76
 
                        FILE_NOTIFY_CHANGE_DIR_NAME |
77
 
                        FILE_NOTIFY_CHANGE_ATTRIBUTES |
78
 
                        FILE_NOTIFY_CHANGE_SIZE |
79
 
                        FILE_NOTIFY_CHANGE_LAST_WRITE |
80
 
                        FILE_NOTIFY_CHANGE_SECURITY);
81
 
 
82
 
                if(h == INVALID_HANDLE_VALUE)
83
 
                        return 0;
84
 
 
85
 
                DWEntry *e = new DWEntry;
86
 
                e->dir = s;
87
 
                e->h = h;
88
 
                e->thread = new DWThread(e, h);
89
 
                e->thread->start();
90
 
                return e;
91
 
        }
92
 
 
93
 
        ~DWEntry()
94
 
        {
95
 
                if(thread) {
96
 
                        FindCloseChangeNotification(h);
97
 
                        thread->wait();
98
 
                        delete thread;
99
 
                }
100
 
        }
101
 
 
102
 
signals:
103
 
        void changed();
104
 
 
105
 
protected:
106
 
        bool event(QEvent *e)
107
 
        {
108
 
                if(e->type() == QEvent::User) {
109
 
                        DWEvent *de = (DWEvent *)e;
110
 
                        // error?
111
 
                        if(de->state == 0) {
112
 
                                thread->wait();
113
 
                                delete thread;
114
 
                                FindCloseChangeNotification(h);
115
 
                                thread = 0;
116
 
                        }
117
 
                        else {
118
 
                                dirty = true;
119
 
                                changed();
120
 
                        }
121
 
 
122
 
                        return true;
123
 
                }
124
 
                return false;
125
 
        }
126
 
 
127
 
public:
128
 
        QString dir;
129
 
        QValueList<int> idList;
130
 
        bool dirty;
131
 
 
132
 
private:
133
 
        DWEntry()
134
 
        {
135
 
                dirty = false;
136
 
        }
137
 
 
138
 
        HANDLE h;
139
 
        DWThread *thread;
140
 
};
141
 
 
142
 
class DirWatchPlatform::Private : public QObject
143
 
{
144
 
        Q_OBJECT
145
 
public:
146
 
        Private(DirWatchPlatform *_par)
147
 
        {
148
 
                par = _par;
149
 
                list.setAutoDelete(true);
150
 
                connect(&t, SIGNAL(timeout()), this, SLOT(slotNotify()));
151
 
        }
152
 
 
153
 
        ~Private()
154
 
        {
155
 
                list.clear();
156
 
        }
157
 
 
158
 
        QTimer t;
159
 
        DirWatchPlatform *par;
160
 
        QPtrList<DWEntry> list;
161
 
 
162
 
        int addItem(const QString &s)
163
 
        {
164
 
                DWEntry *e = findEntryByDir(s);
165
 
                if(!e) {
166
 
                        e = DWEntry::create(s);
167
 
                        if(!e)
168
 
                                return -1;
169
 
                        connect(e, SIGNAL(changed()), SLOT(slotChanged()));
170
 
                        list.append(e);
171
 
                }
172
 
                int id = getUniqueId();
173
 
                e->idList.append(id);
174
 
                return id;
175
 
        }
176
 
 
177
 
        void removeItem(int id)
178
 
        {
179
 
                DWEntry *e = findEntryById(id);
180
 
                if(!e)
181
 
                        return;
182
 
                e->idList.remove(id);
183
 
                if(e->idList.isEmpty())
184
 
                        list.removeRef(e);
185
 
        }
186
 
 
187
 
        int getUniqueId()
188
 
        {
189
 
                for(int n = 0;; ++n) {
190
 
                        QPtrListIterator<DWEntry> it(list);
191
 
                        bool found = false;
192
 
                        for(DWEntry *e; (e = it.current()); ++it) {
193
 
                                for(QValueList<int>::ConstIterator idi = e->idList.begin(); idi != e->idList.end(); ++idi) {
194
 
                                        if(*idi == n) {
195
 
                                                found = true;
196
 
                                                break;
197
 
                                        }
198
 
                                }
199
 
                                if(found)
200
 
                                        break;
201
 
                        }
202
 
                        if(!found)
203
 
                                return n;
204
 
                }
205
 
        }
206
 
 
207
 
        DWEntry * findEntryByDir(const QString &s)
208
 
        {
209
 
                QPtrListIterator<DWEntry> it(list);
210
 
                for(DWEntry *e; (e = it.current()); ++it) {
211
 
                        if(e->dir == s)
212
 
                                return e;
213
 
                }
214
 
                return 0;
215
 
        }
216
 
 
217
 
        DWEntry * findEntryById(int id)
218
 
        {
219
 
                QPtrListIterator<DWEntry> it(list);
220
 
                for(DWEntry *e; (e = it.current()); ++it) {
221
 
                        for(QValueList<int>::ConstIterator idi = e->idList.begin(); idi != e->idList.end(); ++idi) {
222
 
                                if(*idi == id)
223
 
                                        return e;
224
 
                        }
225
 
                }
226
 
                return 0;
227
 
        }
228
 
 
229
 
private slots:
230
 
        void slotChanged()
231
 
        {
232
 
                // use a timer to combine multiple changed events into one
233
 
                if(!t.isActive())
234
 
                        t.start(200, true);
235
 
        }
236
 
 
237
 
        void slotNotify()
238
 
        {
239
 
                // see who is dirty
240
 
                QPtrListIterator<DWEntry> it(list);
241
 
                for(DWEntry *e; (e = it.current()); ++it) {
242
 
                        if(e->dirty) {
243
 
                                e->dirty = false;
244
 
                                for(QValueList<int>::ConstIterator idi = e->idList.begin(); idi != e->idList.end(); ++idi) {
245
 
                                        par->triggerDirChanged(*idi);
246
 
                                }
247
 
                        }
248
 
                }
249
 
        }
250
 
};
251
 
 
252
 
DirWatchPlatform::DirWatchPlatform()
253
 
:QObject(0)
254
 
{
255
 
        d = new Private(this);
256
 
}
257
 
 
258
 
DirWatchPlatform::~DirWatchPlatform()
259
 
{
260
 
        delete d;
261
 
}
262
 
 
263
 
bool DirWatchPlatform::init()
264
 
{
265
 
        return true;
266
 
}
267
 
 
268
 
int DirWatchPlatform::addDir(const QString &s)
269
 
{
270
 
        return d->addItem(s);
271
 
}
272
 
 
273
 
void DirWatchPlatform::removeDir(int id)
274
 
{
275
 
        d->removeItem(id);
276
 
}
277
 
 
278
 
#include"dirwatch_win.moc"