source: branches/alilink/TEMPLATES/FileWatch.h

Last change on this file was 16863, checked in by westram, 7 years ago
File size: 4.1 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    // Warning: be aware that callbacks may be called with empty name (""),
41    //          depending on where awar is used!
42
43    void file_modified_handler(const char *file, ChangeReason reason) const {
44        // - corrects "selected file" in response to filesystem changes (de- and re-select)
45        // - triggers awar callback if file gets modified
46
47        switch (reason) {
48            case CR_CREATED:
49            case CR_MODIFIED:
50                if (awar_selfile->read_char_pntr()[0]) { // awar has content (do not overwrite)
51                    awar_selfile->touch();
52                }
53                else if (GB_is_regularfile(file)) {
54                    awar_selfile->write_string(file);
55                }
56                break;
57            case CR_DELETED:
58                aw_assert(!GB_is_regularfile(file));
59                awar_selfile->write_string("");
60                break;
61        }
62
63    }
64
65    void remove_inotification() {
66        if (watched_file.isSet()) {
67            AW_remove_inotification(&*watched_file, wf_cb);
68            watched_file.setNull();
69        }
70    }
71
72    void awar_modified_handler() {
73        SmartCharPtr file(awar_selfile->read_string());
74
75        bool points_to_file    = GB_is_regularfile(&*file);
76        bool need_change_watch =
77            points_to_file
78            ? (watched_file.isNull() || strcmp(&*watched_file, &*file) != 0)
79            : watched_file.isSet();
80
81        if (need_change_watch) {
82            remove_inotification();
83            if (points_to_file) {
84                watched_file = file;
85                AW_add_inotification(&*watched_file, wf_cb);
86            }
87        }
88
89        user_cb(&*file, CR_MODIFIED);
90    }
91
92    // callback-wrappers
93    static void file_modified_wrapper(const char *file, ChangeReason reason, FileWatch *watch) { watch->file_modified_handler(file, reason); }
94    static void awar_modified_wrapper(AW_root*, FileWatch *watch) { watch->awar_modified_handler(); }
95
96public:
97
98    FileWatch(const char *sel_file_awar, const FileChangedCallback& file_changed_cb) :
99        awar_selfile(AW_root::SINGLETON->awar(sel_file_awar)),
100        wf_cb(makeFileChangedCallback(file_modified_wrapper, this)),
101        user_cb(file_changed_cb)
102    {
103        awar_selfile->add_callback(makeRootCallback(awar_modified_wrapper, this));
104    }
105
106    ~FileWatch() {
107        awar_selfile->remove_callback(makeRootCallback(awar_modified_wrapper, this));
108        remove_inotification();
109    }
110};
111
112#else
113#error FileWatch.h included twice
114#endif // FILEWATCH_H
Note: See TracBrowser for help on using the repository browser.