1/*
2 * Copyright (C) by Klaas Freitag <freitag@owncloud.com>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * for more details.
13 */
14
15#ifndef MIRALL_FOLDERWATCHER_H
16#define MIRALL_FOLDERWATCHER_H
17
18#include "config.h"
19
20#include <QList>
21#include <QLoggingCategory>
22#include <QObject>
23#include <QString>
24#include <QStringList>
25#include <QTime>
26#include <QHash>
27#include <QScopedPointer>
28#include <QSet>
29
30class QTimer;
31
32namespace OCC {
33
34Q_DECLARE_LOGGING_CATEGORY(lcFolderWatcher)
35
36class FolderWatcherPrivate;
37class Folder;
38
39/**
40 * @brief Monitors a directory recursively for changes
41 *
42 * Folder Watcher monitors a directory and its sub directories
43 * for changes in the local file system. Changes are signalled
44 * through the pathChanged() signal.
45 *
46 * Note that if new folders are created, this folderwatcher class
47 * does not automatically add them to the list of monitored
48 * dirs. That is the responsibility of the user of this class to
49 * call addPath() with the new dir.
50 *
51 * @ingroup gui
52 */
53
54class FolderWatcher : public QObject
55{
56 Q_OBJECT
57public:
58 // Construct, connect signals, call init()
59 explicit FolderWatcher(Folder *folder = 0L);
60 virtual ~FolderWatcher();
61
62 /**
63 * @param root Path of the root of the folder
64 */
65 void init(const QString &root);
66
67 /**
68 * Not all backends are recursive by default.
69 * Those need to be notified when a directory is added or removed while the watcher is disabled.
70 * This is a no-op for backends that are recursive
71 */
72 void addPath(const QString &);
73 void removePath(const QString &);
74
75 /* Check if the path is ignored. */
76 bool pathIsIgnored(const QString &path);
77
78 /**
79 * Returns false if the folder watcher can't be trusted to capture all
80 * notifications.
81 *
82 * For example, this can happen on linux if the inotify user limit from
83 * /proc/sys/fs/inotify/max_user_watches is exceeded.
84 */
85 bool isReliable() const;
86
87signals:
88 /** Emitted when one of the watched directories or one
89 * of the contained files is changed. */
90 void pathChanged(const QString &path);
91
92 /**
93 * Emitted if some notifications were lost.
94 *
95 * Would happen, for example, if the number of pending notifications
96 * exceeded the allocated buffer size on Windows. Note that the folder
97 * watcher could still be able to capture all future notifications -
98 * i.e. isReliable() is orthogonal to losing changes occasionally.
99 */
100 void lostChanges();
101
102 /**
103 * Signals when the watcher became unreliable. The string is a translated
104 * message that can be shown to users.
105 */
106 void becameUnreliable(const QString &message);
107
108protected slots:
109 // called from the implementations to indicate a change in path
110 void changeDetected(const QString &path);
111 void changeDetected(const QStringList &paths);
112
113protected:
114 QHash<QString, int> _pendingPathes;
115
116private:
117 QScopedPointer<FolderWatcherPrivate> _d;
118 QTime _timer;
119 QSet<QString> _lastPaths;
120 Folder *_folder;
121 bool _isReliable = true;
122
123 friend class FolderWatcherPrivate;
124};
125}
126
127#endif
128