File: clFileSystemWatcher.cpp

package info (click to toggle)
codelite 17.0.0%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 136,204 kB
  • sloc: cpp: 491,547; ansic: 280,393; php: 10,259; sh: 8,930; lisp: 7,664; vhdl: 6,518; python: 6,020; lex: 4,920; yacc: 3,123; perl: 2,385; javascript: 1,715; cs: 1,193; xml: 1,110; makefile: 804; cobol: 741; sql: 709; ruby: 620; f90: 566; ada: 534; asm: 464; fortran: 350; objc: 289; tcl: 258; java: 157; erlang: 61; pascal: 51; ml: 49; awk: 44; haskell: 36
file content (179 lines) | stat: -rw-r--r-- 4,584 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
#include "clFileSystemWatcher.h"
#include <algorithm>
#include <set>
#include "fileutils.h"

wxDEFINE_EVENT(wxEVT_FILE_MODIFIED, clFileSystemEvent);
wxDEFINE_EVENT(wxEVT_FILE_NOT_FOUND, clFileSystemEvent);

// In milliseconds
#define FILE_CHECK_INTERVAL 500

clFileSystemWatcher::clFileSystemWatcher()
    : m_owner(NULL)
#if CL_FSW_USE_TIMER
    , m_timer(NULL)
#endif
{
#if CL_FSW_USE_TIMER
    Bind(wxEVT_TIMER, &clFileSystemWatcher::OnTimer, this);
#else
    m_watcher.SetOwner(this);
    Bind(wxEVT_FSWATCHER, &clFileSystemWatcher::OnFileModified, this);
#endif
}

clFileSystemWatcher::~clFileSystemWatcher()
{
#if CL_FSW_USE_TIMER
    Stop();
    Unbind(wxEVT_TIMER, &clFileSystemWatcher::OnTimer, this);
#else
    m_watcher.RemoveAll();
    Unbind(wxEVT_FSWATCHER, &clFileSystemWatcher::OnFileModified, this);
#endif
}

void clFileSystemWatcher::SetFile(const wxFileName& filename)
{
#if CL_FSW_USE_TIMER
    if(filename.Exists()) {
        m_files.clear();
        File f;
        f.filename = filename;
        f.lastModified = FileUtils::GetFileModificationTime(filename);
        f.file_size = FileUtils::GetFileSize(filename);
        m_files.insert(std::make_pair(filename.GetFullPath(), f));
    }
#else
    m_watcher.RemoveAll();
    wxFileName dironly = filename;
    dironly.SetFullName(""); // must be directory only
    m_watcher.Add(dironly);
    m_watchedFile = filename; // but we keep the file name for later usage
#endif
}

void clFileSystemWatcher::Start()
{
#if CL_FSW_USE_TIMER
    Stop();

    m_timer = new wxTimer(this);
    m_timer->Start(FILE_CHECK_INTERVAL, true);
#else
#endif
}

void clFileSystemWatcher::Stop()
{
#if CL_FSW_USE_TIMER
    if(m_timer) {
        m_timer->Stop();
    }
    wxDELETE(m_timer);
#else
    m_watcher.RemoveAll();
#endif
}

void clFileSystemWatcher::Clear()
{
#if CL_FSW_USE_TIMER
    Stop();
    m_files.clear();
#else
    m_watcher.RemoveAll();
#endif
}

#if CL_FSW_USE_TIMER
void clFileSystemWatcher::OnTimer(wxTimerEvent& event)
{
    std::set<wxString> nonExistingFiles;
    std::for_each(m_files.begin(), m_files.end(), [&](const std::pair<wxString, clFileSystemWatcher::File>& p) {
        const File& f = p.second;
        const wxFileName& fn = f.filename;
        if(!fn.Exists()) {

            // fire file not found event
            if(GetOwner()) {
                clFileSystemEvent evt(wxEVT_FILE_NOT_FOUND);
                evt.SetPath(fn.GetFullPath());
                GetOwner()->AddPendingEvent(evt);
            }

            // add the missing file to a set
            nonExistingFiles.insert(fn.GetFullPath());
        } else {
            
#ifdef __WXMSW__
            size_t prev_value = f.file_size;
            size_t curr_value = FileUtils::GetFileSize(fn);
#else
            time_t prev_value = f.lastModified;
            time_t curr_value = FileUtils::GetFileModificationTime(fn);
#endif

            if(prev_value != curr_value) {
                // Fire a modified event
                if(GetOwner()) {
                    clFileSystemEvent evt(wxEVT_FILE_MODIFIED);
                    evt.SetPath(fn.GetFullPath());
                    GetOwner()->AddPendingEvent(evt);
                }
            }
#ifdef __WXMSW__
            File updatdFile = f;
            updatdFile.file_size = curr_value;
#else
            // Always update the last modified timestamp
            File updatdFile = f;
            updatdFile.lastModified = curr_value;
#endif
            m_files[fn.GetFullPath()] = updatdFile;
        }
    });

    // Remove the non existing files
    std::for_each(nonExistingFiles.begin(), nonExistingFiles.end(), [&](const wxString& fn) { m_files.erase(fn); });

    if(m_timer) {
        m_timer->Start(FILE_CHECK_INTERVAL, true);
    }
}
#endif

#if !CL_FSW_USE_TIMER
void clFileSystemWatcher::OnFileModified(wxFileSystemWatcherEvent& event)
{
    if(event.GetChangeType() == wxFSW_EVENT_MODIFY) {
        const wxFileName& modpath = event.GetPath();
        if(modpath == m_watchedFile) {
            if(GetOwner()) {
                clFileSystemEvent evt(wxEVT_FILE_MODIFIED);
                evt.SetPath(modpath.GetFullPath());
                GetOwner()->AddPendingEvent(evt);
            }
        }
    }
}
#endif

void clFileSystemWatcher::RemoveFile(const wxFileName& filename)
{
#if CL_FSW_USE_TIMER
    if(m_files.count(filename.GetFullPath())) {
        m_files.erase(filename.GetFullPath());
    }
#endif
}

bool clFileSystemWatcher::IsRunning() const
{
#if CL_FSW_USE_TIMER
    return m_timer;
#else
    return m_watcher.GetWatchedPathsCount();
#endif
}