fswatcher.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411
  1. /////////////////////////////////////////////////////////////////////////////
  2. // Name: wx/fswatcher.h
  3. // Purpose: wxFileSystemWatcherBase
  4. // Author: Bartosz Bekier
  5. // Created: 2009-05-23
  6. // Copyright: (c) 2009 Bartosz Bekier <bartosz.bekier@gmail.com>
  7. // Licence: wxWindows licence
  8. /////////////////////////////////////////////////////////////////////////////
  9. #ifndef _WX_FSWATCHER_BASE_H_
  10. #define _WX_FSWATCHER_BASE_H_
  11. #include "wx/defs.h"
  12. #if wxUSE_FSWATCHER
  13. #include "wx/log.h"
  14. #include "wx/event.h"
  15. #include "wx/evtloop.h"
  16. #include "wx/filename.h"
  17. #include "wx/dir.h"
  18. #include "wx/hashmap.h"
  19. #define wxTRACE_FSWATCHER "fswatcher"
  20. // ----------------------------------------------------------------------------
  21. // wxFileSystemWatcherEventType & wxFileSystemWatcherEvent
  22. // ----------------------------------------------------------------------------
  23. /**
  24. * Possible types of file system events.
  25. * This is a subset that will work fine an all platforms (actually, we will
  26. * see how it works on Mac).
  27. *
  28. * We got 2 types of error events:
  29. * - warning: these are not fatal and further events can still be generated
  30. * - error: indicates fatal error and causes that no more events will happen
  31. */
  32. enum
  33. {
  34. wxFSW_EVENT_CREATE = 0x01,
  35. wxFSW_EVENT_DELETE = 0x02,
  36. wxFSW_EVENT_RENAME = 0x04,
  37. wxFSW_EVENT_MODIFY = 0x08,
  38. wxFSW_EVENT_ACCESS = 0x10,
  39. wxFSW_EVENT_ATTRIB = 0x20, // Currently this is wxGTK-only
  40. // error events
  41. wxFSW_EVENT_WARNING = 0x40,
  42. wxFSW_EVENT_ERROR = 0x80,
  43. wxFSW_EVENT_ALL = wxFSW_EVENT_CREATE | wxFSW_EVENT_DELETE |
  44. wxFSW_EVENT_RENAME | wxFSW_EVENT_MODIFY |
  45. wxFSW_EVENT_ACCESS | wxFSW_EVENT_ATTRIB |
  46. wxFSW_EVENT_WARNING | wxFSW_EVENT_ERROR
  47. #ifdef wxHAS_INOTIFY
  48. ,wxFSW_EVENT_UNMOUNT = 0x2000
  49. #endif
  50. };
  51. // Type of the path watched, used only internally for now.
  52. enum wxFSWPathType
  53. {
  54. wxFSWPath_None, // Invalid value for an initialized watch.
  55. wxFSWPath_File, // Plain file.
  56. wxFSWPath_Dir, // Watch a directory and the files in it.
  57. wxFSWPath_Tree // Watch a directory and all its children recursively.
  58. };
  59. // Type of the warning for the events notifying about them.
  60. enum wxFSWWarningType
  61. {
  62. wxFSW_WARNING_NONE,
  63. wxFSW_WARNING_GENERAL,
  64. wxFSW_WARNING_OVERFLOW
  65. };
  66. /**
  67. * Event containing information about file system change.
  68. */
  69. class WXDLLIMPEXP_FWD_BASE wxFileSystemWatcherEvent;
  70. wxDECLARE_EXPORTED_EVENT(WXDLLIMPEXP_BASE, wxEVT_FSWATCHER,
  71. wxFileSystemWatcherEvent);
  72. class WXDLLIMPEXP_BASE wxFileSystemWatcherEvent: public wxEvent
  73. {
  74. public:
  75. // Constructor for any kind of events, also used as default ctor.
  76. wxFileSystemWatcherEvent(int changeType = 0, int watchid = wxID_ANY) :
  77. wxEvent(watchid, wxEVT_FSWATCHER),
  78. m_changeType(changeType),
  79. m_warningType(wxFSW_WARNING_NONE)
  80. {
  81. }
  82. // Constructor for the error or warning events.
  83. wxFileSystemWatcherEvent(int changeType,
  84. wxFSWWarningType warningType,
  85. const wxString& errorMsg = wxString(),
  86. int watchid = wxID_ANY) :
  87. wxEvent(watchid, wxEVT_FSWATCHER),
  88. m_changeType(changeType),
  89. m_warningType(warningType),
  90. m_errorMsg(errorMsg)
  91. {
  92. }
  93. // Constructor for the normal events carrying information about the changes.
  94. wxFileSystemWatcherEvent(int changeType,
  95. const wxFileName& path, const wxFileName& newPath,
  96. int watchid = wxID_ANY) :
  97. wxEvent(watchid, wxEVT_FSWATCHER),
  98. m_changeType(changeType),
  99. m_warningType(wxFSW_WARNING_NONE),
  100. m_path(path),
  101. m_newPath(newPath)
  102. {
  103. }
  104. /**
  105. * Returns the path at which the event occurred.
  106. */
  107. const wxFileName& GetPath() const
  108. {
  109. return m_path;
  110. }
  111. /**
  112. * Sets the path at which the event occurred
  113. */
  114. void SetPath(const wxFileName& path)
  115. {
  116. m_path = path;
  117. }
  118. /**
  119. * In case of rename(move?) events, returns the new path related to the
  120. * event. The "new" means newer in the sense of time. In case of other
  121. * events it returns the same path as GetPath().
  122. */
  123. const wxFileName& GetNewPath() const
  124. {
  125. return m_newPath;
  126. }
  127. /**
  128. * Sets the new path related to the event. See above.
  129. */
  130. void SetNewPath(const wxFileName& path)
  131. {
  132. m_newPath = path;
  133. }
  134. /**
  135. * Returns the type of file system event that occurred.
  136. */
  137. int GetChangeType() const
  138. {
  139. return m_changeType;
  140. }
  141. virtual wxEvent* Clone() const
  142. {
  143. wxFileSystemWatcherEvent* evt = new wxFileSystemWatcherEvent(*this);
  144. evt->m_errorMsg = m_errorMsg.Clone();
  145. evt->m_path = wxFileName(m_path.GetFullPath().Clone());
  146. evt->m_newPath = wxFileName(m_newPath.GetFullPath().Clone());
  147. evt->m_warningType = m_warningType;
  148. return evt;
  149. }
  150. virtual wxEventCategory GetEventCategory() const
  151. {
  152. // TODO this has to be merged with "similar" categories and changed
  153. return wxEVT_CATEGORY_UNKNOWN;
  154. }
  155. /**
  156. * Returns if this error is an error event
  157. */
  158. bool IsError() const
  159. {
  160. return (m_changeType & (wxFSW_EVENT_ERROR | wxFSW_EVENT_WARNING)) != 0;
  161. }
  162. wxString GetErrorDescription() const
  163. {
  164. return m_errorMsg;
  165. }
  166. wxFSWWarningType GetWarningType() const
  167. {
  168. return m_warningType;
  169. }
  170. /**
  171. * Returns a wxString describing an event useful for debugging or testing
  172. */
  173. wxString ToString() const;
  174. protected:
  175. int m_changeType;
  176. wxFSWWarningType m_warningType;
  177. wxFileName m_path;
  178. wxFileName m_newPath;
  179. wxString m_errorMsg;
  180. private:
  181. DECLARE_DYNAMIC_CLASS_NO_ASSIGN(wxFileSystemWatcherEvent)
  182. };
  183. typedef void (wxEvtHandler::*wxFileSystemWatcherEventFunction)
  184. (wxFileSystemWatcherEvent&);
  185. #define wxFileSystemWatcherEventHandler(func) \
  186. wxEVENT_HANDLER_CAST(wxFileSystemWatcherEventFunction, func)
  187. #define EVT_FSWATCHER(winid, func) \
  188. wx__DECLARE_EVT1(wxEVT_FSWATCHER, winid, wxFileSystemWatcherEventHandler(func))
  189. // ----------------------------------------------------------------------------
  190. // wxFileSystemWatcherBase: interface for wxFileSystemWatcher
  191. // ----------------------------------------------------------------------------
  192. // Simple container to store information about one watched path.
  193. class wxFSWatchInfo
  194. {
  195. public:
  196. wxFSWatchInfo() :
  197. m_events(-1), m_type(wxFSWPath_None), m_refcount(-1)
  198. {
  199. }
  200. wxFSWatchInfo(const wxString& path,
  201. int events,
  202. wxFSWPathType type,
  203. const wxString& filespec = wxString()) :
  204. m_path(path), m_filespec(filespec), m_events(events), m_type(type),
  205. m_refcount(1)
  206. {
  207. }
  208. const wxString& GetPath() const
  209. {
  210. return m_path;
  211. }
  212. const wxString& GetFilespec() const { return m_filespec; }
  213. int GetFlags() const
  214. {
  215. return m_events;
  216. }
  217. wxFSWPathType GetType() const
  218. {
  219. return m_type;
  220. }
  221. // Reference counting of watch entries is used to avoid watching the same
  222. // file system path multiple times (this can happen even accidentally, e.g.
  223. // when you have a recursive watch and then decide to watch some file or
  224. // directory under it separately).
  225. int IncRef()
  226. {
  227. return ++m_refcount;
  228. }
  229. int DecRef()
  230. {
  231. wxASSERT_MSG( m_refcount > 0, wxS("Trying to decrement a zero count") );
  232. return --m_refcount;
  233. }
  234. protected:
  235. wxString m_path;
  236. wxString m_filespec; // For tree watches, holds any filespec to apply
  237. int m_events;
  238. wxFSWPathType m_type;
  239. int m_refcount;
  240. };
  241. WX_DECLARE_STRING_HASH_MAP(wxFSWatchInfo, wxFSWatchInfoMap);
  242. /**
  243. * Encapsulation of platform-specific file system event mechanism
  244. */
  245. class wxFSWatcherImpl;
  246. /**
  247. * Main entry point for clients interested in file system events.
  248. * Defines interface that can be used to receive that kind of events.
  249. */
  250. class WXDLLIMPEXP_BASE wxFileSystemWatcherBase: public wxEvtHandler
  251. {
  252. public:
  253. wxFileSystemWatcherBase();
  254. virtual ~wxFileSystemWatcherBase();
  255. /**
  256. * Adds path to currently watched files. Any events concerning this
  257. * particular path will be sent to handler. Optionally a filter can be
  258. * specified to receive only events of particular type.
  259. *
  260. * Please note that when adding a dir, immediate children will be watched
  261. * as well.
  262. */
  263. virtual bool Add(const wxFileName& path, int events = wxFSW_EVENT_ALL);
  264. /**
  265. * Like above, but recursively adds every file/dir in the tree rooted in
  266. * path. Additionally a file mask can be specified to include only files
  267. * of particular type.
  268. */
  269. virtual bool AddTree(const wxFileName& path, int events = wxFSW_EVENT_ALL,
  270. const wxString& filespec = wxEmptyString);
  271. /**
  272. * Removes path from the list of watched paths.
  273. */
  274. virtual bool Remove(const wxFileName& path);
  275. /**
  276. * Same as above, but also removes every file belonging to the tree rooted
  277. * at path.
  278. */
  279. virtual bool RemoveTree(const wxFileName& path);
  280. /**
  281. * Clears the list of currently watched paths.
  282. */
  283. virtual bool RemoveAll();
  284. /**
  285. * Returns the number of watched paths
  286. */
  287. int GetWatchedPathsCount() const;
  288. /**
  289. * Retrevies all watched paths and places them in wxArrayString. Returns
  290. * the number of paths.
  291. *
  292. * TODO think about API here: we need to return more information (like is
  293. * the path watched recursively)
  294. */
  295. int GetWatchedPaths(wxArrayString* paths) const;
  296. wxEvtHandler* GetOwner() const
  297. {
  298. return m_owner;
  299. }
  300. void SetOwner(wxEvtHandler* handler)
  301. {
  302. if (!handler)
  303. m_owner = this;
  304. else
  305. m_owner = handler;
  306. }
  307. // This is a semi-private function used by wxWidgets itself only.
  308. //
  309. // Delegates the real work of adding the path to wxFSWatcherImpl::Add() and
  310. // updates m_watches if the new path was successfully added.
  311. bool AddAny(const wxFileName& path, int events, wxFSWPathType type,
  312. const wxString& filespec = wxString());
  313. protected:
  314. static wxString GetCanonicalPath(const wxFileName& path)
  315. {
  316. wxFileName path_copy = wxFileName(path);
  317. if ( !path_copy.Normalize() )
  318. {
  319. wxFAIL_MSG(wxString::Format("Unable to normalize path '%s'",
  320. path.GetFullPath()));
  321. return wxEmptyString;
  322. }
  323. return path_copy.GetFullPath();
  324. }
  325. wxFSWatchInfoMap m_watches; // path=>wxFSWatchInfo map
  326. wxFSWatcherImpl* m_service; // file system events service
  327. wxEvtHandler* m_owner; // handler for file system events
  328. friend class wxFSWatcherImpl;
  329. };
  330. // include the platform specific file defining wxFileSystemWatcher
  331. // inheriting from wxFileSystemWatcherBase
  332. #ifdef wxHAS_INOTIFY
  333. #include "wx/unix/fswatcher_inotify.h"
  334. #define wxFileSystemWatcher wxInotifyFileSystemWatcher
  335. #elif defined(wxHAS_KQUEUE)
  336. #include "wx/unix/fswatcher_kqueue.h"
  337. #define wxFileSystemWatcher wxKqueueFileSystemWatcher
  338. #elif defined(__WINDOWS__)
  339. #include "wx/msw/fswatcher.h"
  340. #define wxFileSystemWatcher wxMSWFileSystemWatcher
  341. #else
  342. #include "wx/generic/fswatcher.h"
  343. #define wxFileSystemWatcher wxPollingFileSystemWatcher
  344. #endif
  345. #endif // wxUSE_FSWATCHER
  346. #endif /* _WX_FSWATCHER_BASE_H_ */