source: tags/ms_r17q3/TEMPLATES/FileWatch.h

Last change on this file was 16564, checked in by westram, 7 years ago
File size: 4.0 KB
Line 
1// =============================================================== //
2//                                                                 //
3//   File      : FileWatch.h                                       //
4//   Purpose   : Watch awar pointing to file AND file itself       //
5//                                                                 //
6//   Coded by Ralf Westram (coder@reallysoft.de) in October 2017   //
7//   http://www.arb-home.de/                                       //
8//                                                                 //
9// =============================================================== //
10
11#ifndef FILEWATCH_H
12#define FILEWATCH_H
13
14#ifndef AW_AWAR_HXX
15#include <aw_awar.hxx>
16#endif
17#ifndef AW_ROOT_HXX
18#include <aw_root.hxx>
19#endif
20#ifndef AW_INOTIFY_HXX
21#include <aw_inotify.hxx>
22#endif
23#ifndef ARB_FILE_H
24#include <arb_file.h>
25#endif
26
27/*  Binds user-callback to an awar which contains a filename (full-path; e.g. from File_selection)
28 *  - the user-callback will be called whenever the awar triggers
29 *  - the awar will automatically change when
30 *    - it points to a file and the file gets modified (awar gets touched)
31 *    - the file is deleted (awar changes to "")
32 *    - the file is re-created (if awar is "" -> awar points to file again)
33 */
34
35class FileWatch : virtual Noncopyable {
36    AW_awar             *awar_selfile; // contains name of file (or sth invalid like "")
37    SmartCharPtr         watched_file; // if set -> currently watched file
38    FileChangedCallback  wf_cb;        // used to watch file changes
39    FileChangedCallback  user_cb;      // called if awar or (pointed-to) file changes
40
41    void file_modified_handler(const char *file, ChangeReason reason) const {
42        // - corrects "selected file" in response to filesystem changes (de- and re-select)
43        // - triggers awar callback if file gets modified
44
45        switch (reason) {
46            case CR_CREATED:
47            case CR_MODIFIED:
48                if (awar_selfile->read_char_pntr()[0]) { // awar has content (do not overwrite)
49                    awar_selfile->touch();
50                }
51                else if (GB_is_regularfile(file)) {
52                    awar_selfile->write_string(file);
53                }
54                break;
55            case CR_DELETED:
56                aw_assert(!GB_is_regularfile(file));
57                awar_selfile->write_string("");
58                break;
59        }
60
61    }
62
63    void remove_inotification() {
64        if (watched_file.isSet()) {
65            AW_remove_inotification(&*watched_file, wf_cb);
66            watched_file.setNull();
67        }
68    }
69
70    void awar_modified_handler() {
71        SmartCharPtr file(awar_selfile->read_string());
72
73        bool points_to_file    = GB_is_regularfile(&*file);
74        bool need_change_watch =
75            points_to_file
76            ? (watched_file.isNull() || strcmp(&*watched_file, &*file) != 0)
77            : watched_file.isSet();
78
79        if (need_change_watch) {
80            remove_inotification();
81            if (points_to_file) {
82                watched_file = file;
83                AW_add_inotification(&*watched_file, wf_cb);
84            }
85        }
86
87        user_cb(&*file, CR_MODIFIED);
88    }
89
90    // callback-wrappers
91    static void file_modified_wrapper(const char *file, ChangeReason reason, FileWatch *watch) { watch->file_modified_handler(file, reason); }
92    static void awar_modified_wrapper(AW_root*, FileWatch *watch) { watch->awar_modified_handler(); }
93
94public:
95
96    FileWatch(const char *sel_file_awar, const FileChangedCallback& file_changed_cb) :
97        awar_selfile(AW_root::SINGLETON->awar(sel_file_awar)),
98        wf_cb(makeFileChangedCallback(file_modified_wrapper, this)),
99        user_cb(file_changed_cb)
100    {
101        awar_selfile->add_callback(makeRootCallback(awar_modified_wrapper, this));
102    }
103
104    ~FileWatch() {
105        awar_selfile->remove_callback(makeRootCallback(awar_modified_wrapper, this));
106        remove_inotification();
107    }
108};
109
110#else
111#error FileWatch.h included twice
112#endif // FILEWATCH_H
Note: See TracBrowser for help on using the repository browser.